package org.sdnstproject.interlayer.OF13Protocal;

import java.util.Random;
import org.projectfloodlight.openflow.types.U32;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;

public class FuError {
	private static final Logger log = LoggerFactory.getLogger(FuError.class);
    public byte version = (byte)4;
    public byte type = (byte)1;
    public short length = (short)12;// MINIMUM_LENGTH = 12;
    public long xid = 0x0L;
    public short errType = (short)1;// fixed value property statsType = 1
    /*public final static short BAD_VERSION_VAL = (short) 0x0;
    public final static short BAD_TYPE_VAL = (short) 0x1;
    public final static short BAD_STAT_VAL = (short) 0x2;
    public final static short BAD_EXPERIMENTER_VAL = (short) 0x3;
    public final static short BAD_EXPERIMENTER_TYPE_VAL = (short) 0x4;
    public final static short EPERM_VAL = (short) 0x5;
    public final static short BAD_LEN_VAL = (short) 0x6;
    public final static short BUFFER_EMPTY_VAL = (short) 0x7;
    public final static short BUFFER_UNKNOWN_VAL = (short) 0x8;
    public final static short BAD_TABLE_ID_VAL = (short) 0x9;
    public final static short IS_SLAVE_VAL = (short) 0xa;
    public final static short BAD_PORT_VAL = (short) 0xb;
    public final static short BAD_PACKET_VAL = (short) 0xc;
    public final static short MULTIPART_BUFFER_OVERFLOW_VAL = (short) 0xd;
     * */
    public short code =(short) 0x1;
    public byte[] data = new byte[] {};//DEFAULT_METER_ID = 0x0L;
	
	public FuError() {
		
	}
	
	public FuError setXid(long xid) {
		this.xid = xid;
		return this;
	}
	
	public FuError setField(String field, String value) {
		switch (field) {
		case "version":
			this.version = Byte.parseByte(value);
			break;
		case "type":
			this.type = Byte.parseByte(value);
			break;
		case "length":
			this.length = Short.parseShort(value);
			break;
		case "xid":
			this.xid = Long.parseLong(value);
			break;
		case "errType":
			this.errType = Short.parseShort(value);
			break;
		case "code":
			this.code = Short.parseShort(value);
			break;
		case "data":
			this.data = new byte[new Random().nextInt(100)+60];//TODO 
			new Random().nextBytes(data);
			break;
		}
		return this;
	}
	
	public ByteBuf writeTo() {
		ByteBuf bb = Unpooled.directBuffer();
		int startIndex = bb.writerIndex();
        // fixed value property version = 4
        bb.writeByte(version);
        // fixed value property type = 1
        bb.writeByte(type);
        // length is length of variable message, will be updated at the end
        int lengthIndex = bb.writerIndex();
        bb.writeShort(length);

        bb.writeInt(U32.t(xid));
        // fixed value property statsType = 1
        bb.writeShort(errType);
        bb.writeShort(code);
        bb.writeBytes(data);

        // update length field
        length = (short)(bb.writerIndex() - startIndex);
        bb.setShort(lengthIndex, length);
        return bb;
    }
	
	@Override
    public String toString() {
        StringBuilder b = new StringBuilder("OFErrorVer13(");
        b.append("version=").append(version);
        b.append(", ");
        b.append("type=").append(type);
        b.append(", ");
        b.append("length=").append(length);
        b.append(", ");
        b.append("xid=").append(xid);
        b.append(",");
        b.append("errType=").append(errType);
        b.append(", ");
        b.append("code=").append(code);
        b.append(", ");
        b.append("data=").append(data);
        b.append(")");
        return b.toString();
    }
}
